<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      *,
      :before,
      :after {
        box-sizing: border-box;
      }

      :before,
      :after {
        display: none;
        content: "";
      }

      html,
      body {
        margin: 0;
        padding: 0;
      }

      html {
        background-color: #212121;
      }

      body {
        display: flex;
        align-items: center;
        min-height: 100vh;
        min-width: 100vw;
      }

      .clock {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 80%;
        max-width: 40rem;
        margin: 0 auto;
      }

      .clock__number {
        position: relative;
        display: inline-block;
        overflow: hidden;
        min-width: 13rem;
        margin: 0 0.5rem;
        background-color: #252525;
        background-image: linear-gradient(#363636, #252525);
        border-radius: 12px;
        font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica,
          Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
        font-size: 8rem;
        font-weight: bold;
        text-align: center;
        letter-spacing: 1px;
        color: #ffffff;
        perspective: 1000px;
        transform-style: preserve-3d;
      }

      .clock__number,
      .clock__number:before {
        padding: 1rem;
      }

      .clock__number:before {
        display: flex;
        align-items: flex-end;
        justify-content: center;
        content: attr(data-time);
        position: absolute;
        top: 50%;
        left: 0;
        width: 100%;
        height: 50%;
        opacity: 0;
        overflow: hidden;
        transform-origin: top;
      }

      .clock__number:after {
        display: block;
        position: absolute;
        top: 4px;
        left: 0;
        width: 100%;
        height: 50%;
        border-bottom: 4px solid #212121;
      }

      .flip:before {
        animation: flip ease-in-out 600ms -100ms;
      }

      @keyframes flip {
        0% {
          opacity: 0;
          background-color: #252525;
          color: #252525;
          transform: rotateX(180deg);
        }
        15% {
          opacity: 1;
        }
        90% {
          background-color: transparent;
          color: inherit;
          transform: rotateX(0);
        }
        100% {
          opacity: 0;
        }
      }
    </style>
  </head>
  <body>
    <div class="clock">
      <span class="clock__number clock__number--hours" data-time="12">--</span>
      <span class="clock__number clock__number--minutes" data-time="12"
        >--</span
      >
      <script>
        const app = {
          init() {
            this.cacheDOM();
          },

          cacheDOM() {
            this.clock = document.querySelector(".clock");
            this.hours = this.clock.querySelector(".clock__number--hours");
            this.minutes = this.clock.querySelector(".clock__number--minutes");

            this.bindEvents();
          },

          bindEvents() {
            // get time when app is initialized
            this.getTime();

            // get time every 1 second
            setInterval(() => {
              this.getTime();
            }, 1000);
          },

          getTime() {
            const date = new Date();
            const time = {
              hours: this.pad(date.getHours()),
              minutes: this.pad(date.getMinutes()),
            };

            this.appendTime(time);
          },

          appendTime(time) {
            // only change dom if the time has updated
            if (this.hours.innerText != time.hours)
              this.flip(this.hours, time.hours);

            if (this.minutes.innerText != time.minutes)
              this.flip(this.minutes, time.minutes);
          },

          flip(elm, time) {
            // flip before update time
            elm.classList.add("flip");

            elm.dataset.time = time;
            elm.innerText = time;

            setTimeout(() => {
              elm.classList.remove("flip");
            }, 1000);
          },

          pad(number) {
            // return number as 2 chars
            const fixNumber = number.toString();

            return fixNumber.length < 2 ? `0${fixNumber}` : fixNumber;
          },
        };

        app.init();
      </script>
    </div>
  </body>
</html>
